package parser;

import java.util.ArrayList;
import java.util.Stack;

import lex.Scanner;
import common.Enum;
import common.Error;
import common.Node;
import common.Production;
import common.SNLPredict;
import common.SNLProduction;
import common.TreeNode;

public class Parser {

	static SNLProduction Product = new SNLProduction();
	static SNLPredict Predict = new SNLPredict();
	private Scanner Scanner = new Scanner();
	static ArrayList<Node> TokenList = new ArrayList<Node>();
	static int cur;
	static int[][] LL1;

	public Parser() {
		cur = 0;

		LL1 = new int[67][41];
		// 初始化为-1表示错误
		for (int i = 0; i < 67; i++) {
			for (int j = 0; j < 41; j++) {
				LL1[i][j] = -1;
			}
		}

		// 遍历所有产生式的predict集,初始化LL1分析表
		for (int i = 1; i < 105; i++) {
			common.Predict predict = Predict.predict[i];
			int row = Product.product[i].getHead().ordinal();

			int colnum = predict.getPredictNum();
			for (int j = 0; j < colnum; j++) {
				int col = predict.getPredict(j).ordinal();
				LL1[row][col] = i;
			}
		}

		// for (int i = 0; i < 67; i++) {
		// for (int j = 0; j < 41; j++) {
		// System.out.print(LL1[i][j] + "\t");
		// }
		// System.out.println();
		// }

	}

	/**
	 * 递归地匹配一个非终极符
	 * 
	 * @param NonTerminal
	 * @param father
	 * @return
	 */
	public TreeNode match(Enum.nonTerminals NonTerminal, TreeNode father) {

		int i, j, choose = -1;// 选择的产生式编号
		TreeNode root = new TreeNode();
		Enum.nonTerminals temp;
		Enum.lexType curLex = TokenList.get(cur).getType();

		root.setflag(1);
		root.setNonTerminal(NonTerminal);
		root.setFather(father);

		// 查找应该选择哪条产生式
		for (i = 1; i <= 104; i++) {
			int flag = 0;
			temp = Product.product[i].getHead();
			for (j = 0; j < Predict.predict[i].getPredictNum(); j++) {
				if (curLex == Predict.predict[i].getPredict(j)) {
					flag = 1;
					break;
				}
			}
			if (flag == 1 && temp == NonTerminal) {
				choose = i;
				break;
			}
		}

		if (choose == -1) {
			// 没找到, 报错
			Error.setError(TokenList.get(cur).getLine(), TokenList.get(cur)
					.getRow(), 2);
			return null;
		} else {
			// 找到了,处理产生式右部各子部
			for (i = 0; i < Product.product[choose].getproductNum(); i++) {
				if (Product.product[choose].getflag(i) == 0) {
					// 如果为终级符,创建叶子节点
					TreeNode leaf = new TreeNode();
					leaf.setFather(father);
					leaf.setflag(0);
					leaf.setTerminal(Product.product[choose]
							.getProductTerminal(i));
					leaf.setData(TokenList.get(cur).getData());
					root.setChild(leaf);
					cur++;// 处理下一个TOKEN
				} else {
					// 如果为非终级符
					TreeNode child;
					Enum.nonTerminals NonTerminals = Product.product[choose]
							.getProductNonterminal(i);
					child = match(NonTerminals, root);
					root.setChild(child);
				}
			}
		}

		return root;
	}

	/**
	 * 得到一个语法分析树，返回树根
	 * 
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public TreeNode getTree(String filePath) throws Exception {

		TokenList = Scanner.getTokenList(filePath);

		if (Error.getFlag() == true) {
			return null;
		} else {
			TreeNode root = new TreeNode();
			cur = 0;
			root = match(Enum.nonTerminals.Program, root);
			if (TokenList.get(cur).getType() != Enum.lexType.ENDFILE) {
				Error.setError(TokenList.get(cur).getLine(), TokenList.get(cur)
						.getRow(), 2);
			}
			if (Error.getFlag() == true) {
				Error.printError();
				return null;
			}
			return root;
		}
	}

	/**
	 * 得到一个语法分析树，返回树根
	 * 
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public TreeNode getTree1(String filePath) throws Exception {

		TokenList = Scanner.getTokenList(filePath);


		if (Error.getFlag() == true) {


			return null;
		} else {
			// 没有出错

			TreeNode root = null;

			Stack<Production.product> analyStack = new Stack<Production.product>();
			// 内部类实例化
			Production.product initProduct = new Production().new product();
			initProduct.flag = 1;
			initProduct.nonterminals = Enum.nonTerminals.Program;
			analyStack.push(initProduct);

			Stack<TreeNode> fatherNodeStack = new Stack<TreeNode>();

			for (cur = 0; cur < TokenList.size(); cur++) {
				Node node = TokenList.get(cur);
				if (analyStack.empty()) {
					break;
				}
				Production.product peekPro = analyStack.peek();
				if (peekPro.flag == 0) {
					// 终级符匹配
					if (peekPro.terminals.equals(node.getType())) {
						// 匹配成功,创建节点,并出栈
						TreeNode treeNode = new TreeNode();
						treeNode.setData(node.getData());
						treeNode.setFather(fatherNodeStack.peek());
						treeNode.setflag(0);
						treeNode.setTerminal(node.getType());
						treeNode.setLine(node.getLine());

						fatherNodeStack.peek().setChild(treeNode);

						analyStack.pop();
						fatherNodeStack.pop();
					} else {
						// 匹配失败,报错
						Error.setError(node.getLine(), node.getRow(), 2);
						Error.printError();
					}
				} else {
					// 非终级符, 查表替换
					cur--;
					int row = peekPro.nonterminals.ordinal();
					int col = node.getType().ordinal();
					int res = LL1[row][col];
					if (res == -1) {

						// 报错
						Error.setError(node.getLine(), node.getRow(), 2);
						Error.printError();
					} else {
						// 得到产生式编号, 出栈, 入栈操作

						// 出栈
						TreeNode treeNode = new TreeNode();
						treeNode.setData(node.getData());

						treeNode.setflag(1);
						treeNode.setNonTerminal(peekPro.nonterminals);
						analyStack.pop();
						if (fatherNodeStack.empty()) {
							treeNode.setFather(null);
							root = treeNode;
						} else {
							treeNode.setFather(fatherNodeStack.peek());
							fatherNodeStack.peek().setChild(treeNode);
							fatherNodeStack.pop();
						}

						// 入栈
						Production prod = Product.product[res];
						for (int i = prod.getproductNum() - 1; i >= 0; i--) {
							analyStack.push(prod.Product[i]);
							fatherNodeStack.push(treeNode);
						}
					}
				}

			}

			if (cur != TokenList.size() - 1) {

				// 报错
				Error.setError(TokenList.get(cur).getLine(), TokenList.get(cur)
						.getRow(), 2);
				Error.printError();
			}
			return root;
		}
	}

}
